package entites;

import utils.LANPackage;
import utils.PackageType;

import eduni.simjava.Sim_entity;
import eduni.simjava.Sim_event;
import eduni.simjava.Sim_port;
import eduni.simjava.Sim_stat;
import eduni.simjava.Sim_system;
import eduni.simjava.distributions.Sim_negexp_obj;

public class LAN extends Sim_entity {

	private Sim_negexp_obj delayer;
	private Sim_port fromSpooler, fromPrinter, toSpooler;
	private Sim_stat stat;

	public LAN(String name, double mean) {
		super(name);

		// Configuração da distribuição
		this.delayer = new Sim_negexp_obj(name, mean);
		this.add_generator(this.delayer);

		// Configuração das portas
		this.toSpooler = new Sim_port("toSpooler");
		this.add_port(toSpooler);
		this.fromSpooler = new Sim_port("fromSpooler");
		this.add_port(fromSpooler);
		this.fromPrinter = new Sim_port("fromPrinter");
		this.add_port(fromPrinter);

		// Configuração das medidas que serao feitas
		this.stat = new Sim_stat();
		this.stat.add_measure(Sim_stat.QUEUE_LENGTH);
		this.stat.add_measure(Sim_stat.RESIDENCE_TIME);
		this.stat.add_measure(Sim_stat.THROUGHPUT);
		this.stat.add_measure(Sim_stat.UTILISATION);
		this.stat.add_measure(Sim_stat.WAITING_TIME);
		this.stat.add_measure(Sim_stat.SERVICE_TIME);
		this.set_stat(this.stat);

	}

	private void route(Sim_event info) {
		if (info.get_tag() < 0) {
			return;
		}

		PackageType packegeType = PackageType.values()[info.get_tag()];
		this.sim_process(this.delayer.sample());

		LANPackage lanPackage = (LANPackage) info.get_data();

		switch (packegeType) {
		case RESPONSE:
			this.sim_schedule(this.toSpooler, 0.0,
					PackageType.RESPONSE.ordinal(), lanPackage);
			break;
		case PRINT_JOB:
			this.sim_schedule(lanPackage.get("PRINTER").toString(), 0.0,
					PackageType.REQUEST.ordinal(), lanPackage);
			break;
		}
	}

	@Override
	public void body() {
		while (Sim_system.running()) {
			Sim_event e = new Sim_event();
			this.sim_get_next(e);
			this.route(e);
			this.sim_completed(e);
		}
	}
}
